home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HAM Radio 3.2
/
Ham Radio Version 3.2 (Chestnut CD-ROMs)(1993).ISO
/
packet
/
n17jsrc
/
popcli.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-05-15
|
10KB
|
477 lines
/*
* POP2 Client routines. Originally authored by Mike Stockett
* (WA7DYX).
* Modified 27 May 1990 by Allen Gwinn (N5CKP) for compatibility
* with later releases (NOS0522).
* Added into NOS by PA0GRI (and linted into "standard" C)
*
* Some code culled from previous releases of SMTP.
*
* Client routines for Simple Mail Transfer Protocol ala RFC821
* A.D. Barksdale Garbee II, aka Bdale, N3EUA
* Copyright 1986 Bdale Garbee, All Rights Reserved.
* Permission granted for non-commercial copying and use, provided
* this notice is retained.
* Modified 14 June 1987 by P. Karn for symbolic target addresses,
* also rebuilt locking mechanism
* Copyright 1987 1988 David Trulli, All Rights Reserved.
* Permission granted for non-commercial copying and use, provided
* this notice is retained.
*/
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <setjmp.h>
#ifdef UNIX
#include <sys/types.h>
#endif
#ifdef __TURBOC__
#include <dir.h>
#include <io.h>
#endif
#include "global.h"
#ifdef ANSIPROTO
#include <stdarg.h>
#endif
#include "mbuf.h"
#include "cmdparse.h"
#include "proc.h"
#include "socket.h"
#include "timer.h"
#include "netuser.h"
#include "dirutil.h"
#include "files.h"
extern char Badhost[];
#define BUF_LEN 257
/* POP client control block */
struct pop_ccb {
int socket; /* socket for this connection */
char state; /* client state */
#define CALL 0
#define NMBR 3
#define SIZE 5
#define XFER 8
#define EXIT 10
char buf[BUF_LEN], /* tcp input buffer */
count; /* input buffer length */
int folder_len; /* number of msgs in current folder */
long msg_len; /* length of current msg */
int msg_num; /* current message number */
} *ccb;
#define NULLCCB (struct pop_ccb *)0
static int Popquiet = 0;
static struct timer popcli_t;
static int32 mailhost;
static char mailbox_name[10],
mailbox_pathname[BUF_LEN],
username[20],
password[20],
Workfile_name[] ="mbox.pop";
static int domailbox __ARGS((int argc,char *argv[],void *p));
static int domailhost __ARGS((int argc,char *argv[],void *p));
static int douserdata __ARGS((int argc,char *argv[],void *p));
static int doquiet __ARGS((int argc,char *argv[],void *p));
static int dotimer __ARGS((int argc,char *argv[],void *p));
static struct pop_ccb *new_ccb __ARGS((void));
static void delete_ccb __ARGS((void));
static void pop_send __ARGS((int unused,void *cb1,void *p));
static int popkick __ARGS((int argc,char *argv[],void *p));
static struct cmds Popcmds[] = {
"mailbox", domailbox, 0, 0, NULLCHAR,
"mailhost", domailhost, 0, 0, NULLCHAR,
"kick", popkick, 0, 0, NULLCHAR,
"quiet", doquiet, 0, 0, NULLCHAR,
"timer", dotimer, 0, 0, NULLCHAR,
"userdata", douserdata, 0, 0, NULLCHAR,
NULLCHAR,
};
/* Command string specifications */
static char ackd_cmd[] = "ACKD\n",
#ifdef POP_FOLDERS
fold_cmd[] = "FOLD %s\n",
#endif
login_cmd[] = "HELO %s %s\n",
/* nack_cmd[] = "NACK\n", /* Not implemented */
quit_cmd[] = "QUIT\n",
read_cur_cmd[] = "READ\n",
retr_cmd[] = "RETR\n";
/* Response string keys */
static char *greeting_rsp = "+ POP2 ";
FILE *fd;
#define NULLFILE (FILE *)0
int
dopop(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return subcmd(Popcmds,argc,argv,p);
}
static int
domailbox(argc,argv,p)
int argc;
char *argv[];
void *p;
{
if(argc < 2) {
if(mailbox_name[0] == '\0')
tprintf("maibox name not set yet\n");
else
tprintf("%s\n",mailbox_name);
} else {
strncpy(mailbox_name,argv[1],10);
}
return 0;
}
static int
domailhost(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int32 n;
if(argc < 2) {
tprintf("%s\n",inet_ntoa(mailhost));
} else
if((n = resolve(argv[1])) == 0) {
tprintf(Badhost,argv[1]);
return 1;
} else
mailhost = n;
return 0;
}
static int
doquiet(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setbool(&Popquiet,"POP quiet",argc,argv);
}
static int
douserdata(argc,argv,p)
int argc;
char *argv[];
void *p;
{
if (argc < 2)
tprintf("%s\n",username);
else if (argc != 3) {
tprintf("Usage: pop userdata <username> <password>\n");
return 1;
} else {
sscanf(argv[1],"%18s",username);
sscanf(argv[2],"%18s",password);
}
return 0;
}
/* Set scan interval */
static int
dotimer(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int poptick();
if(argc < 2) {
tprintf("%lu/%lu\n",
read_timer(&popcli_t)/1000L,
dur_timer(&popcli_t)/1000L);
return 0;
}
popcli_t.func = (void (*)())poptick; /* what to call on timeout */
popcli_t.arg = NULL; /* dummy value */
set_timer(&popcli_t,atol(argv[1])*1000L); /* set timer duration */
start_timer(&popcli_t); /* and fire it up */
return 0;
}
static int
popkick(argc,argv,p)
int argc;
char *argv[];
void *p;
{
poptick(NULL);
return 0;
}
int
poptick()
{
if (ccb == NULLCCB) {
/* Don't start if any of the required parameters have not been specified */
if (mailhost == 0) {
tprintf("mailhost not defined yet.(pop mailhost <host>)\n");
return 0;
}
if (mailbox_name[0] == '\0') {
tprintf("mailbox name not defined yet.(pop mailbox <name>)\n");
return 0;
}
if (username[0] == '\0') {
tprintf("username not defined yet. (pop user <name> <pass>)\n");
return 0;
}
if (password[0] == '\0') {
tprintf(" Unknown password\n");
return 0;
}
if ((ccb = new_ccb()) == NULLCCB) {
fprintf(stderr,"*** Unable to allocate CCB");
return 0;
}
newproc("Auto-POP Client",1024,pop_send,0,ccb,NULL,0);
}
/* Restart timer */
start_timer(&popcli_t);
return 0;
}
/* this is the master state machine that handles a single SMTP transaction */
/* it is called with a queue of jobs for a particular host. */
static void
pop_send(unused,cb1,p)
int unused;
void *cb1;
void *p;
{
char *cp;
struct sockaddr_in fsocket;
struct pop_ccb *ccb;
void pop_csm(struct pop_ccb *);
void quit_session(struct pop_ccb *);
ccb = (struct pop_ccb *)cb1;
fsocket.sin_family = AF_INET;
fsocket.sin_addr.s_addr = mailhost;
fsocket.sin_port = IPPORT_POP;
ccb->socket = socket(AF_INET,SOCK_STREAM,0);
ccb->state = CALL;
if (connect(ccb->socket,(char *)&fsocket,SOCKSIZE) == 0) {
log(ccb->socket,"Connected to mailhost %s", inet_ntoa(mailhost));
} else {
cp = sockerr(ccb->socket);
log(ccb->socket,"Connect to mailhost %s failed: %s", inet_ntoa(mailhost),
(cp != NULLCHAR)? cp: "");
}
while(1) {
if (recvline(ccb->socket,ccb->buf,BUF_LEN) == -1)
goto quit;
rip(ccb->buf);
pop_csm(ccb);
if (ccb->state == EXIT)
goto quit;
}
quit:
log(ccb->socket,"Connection closed to mailhost %s", inet_ntoa(mailhost));
(void) close_s(ccb->socket);
if (fd != NULLFILE)
fclose(fd);
delete_ccb();
}
/* free the message struct and data */
static void
delete_ccb()
{
if (ccb == NULLCCB)
return;
free((char *)ccb);
ccb = NULLCCB;
}
/* create a new pop control block */
static struct
pop_ccb *new_ccb()
{
register struct pop_ccb *ccb;
if ((ccb = (struct pop_ccb *) callocw(1,sizeof(struct pop_ccb))) == NULLCCB)
return(NULLCCB);
return(ccb);
}
/* ---------------------- pop client code starts here --------------------- */
void
pop_csm(ccb)
struct pop_ccb *ccb;
{
FILE *mf;
int mlock (char *,char *);
int rmlock (char * ,char *);
void quit_session __ARGS((struct pop_ccb *));
/* int mlock __ARGS((char *dir,char *id)); */
/* int rmlock __ARGS((char *dir,char *id)); */
switch(ccb->state) {
case CALL:
if (strncmp(ccb->buf,greeting_rsp,strlen(greeting_rsp)) == 0) {
(void)usprintf(ccb->socket,login_cmd,username,password);
ccb->state = NMBR;
} else
(void) quit_session(ccb);
break;
case NMBR:
switch (ccb->buf[0]) {
case '#':
if ((fd = fopen(Workfile_name,"a+")) == NULLFILE) {
perror("Unable to open work file");
quit_session(ccb);
return;
}
fseek(fd,0,SEEK_SET);
ccb->folder_len = atoi(&(ccb->buf[1]));
(void)usprintf(ccb->socket,read_cur_cmd);
ccb->state = SIZE;
break;
case '+':
/* If there is no mail (the only time we get a "+"
* response back at this stage of the game),
* then just close out the connection, because
* there is nothing more to do!! */
default:
quit_session(ccb);
break;
}
break;
case SIZE:
if (ccb->buf[0] == '=') {
ccb->msg_len = atol(&(ccb->buf[1]));
if (ccb->msg_len > 0) {
(void)usprintf(ccb->socket,retr_cmd);
ccb->state = XFER;
} else {
log(ccb->socket,"POP client retrieved %d messages",
ccb->folder_len);
/* All done, so do local cleanup */
if (mlock(Mailspool,mailbox_name)) {
tprintf("\n*** Local mailbox locked, new mail in file %s\n",
Workfile_name);
quit_session(ccb);
return;
}
sprintf(mailbox_pathname,"%s/%s.txt",Mailspool,
mailbox_name);
if ((mf = fopen(mailbox_pathname,"a+")) == NULL) {
tprintf("\n*** Unable to open local mailbox, new mail in file %s\n",
Workfile_name);
quit_session(ccb);
return;
}
fseek(fd,0,SEEK_SET);
while (!feof(fd)) {
if(fgets(ccb->buf,BUF_LEN,fd) != NULLCHAR) {
fputs(ccb->buf,mf);
}
}
fclose(mf);
fclose(fd);
fd = NULL;
tprintf("New mail arrived for %s from mailhost <%s>%c\n",
mailbox_name, inet_ntoa(mailhost),
Popquiet ? ' ' : '\007');
rmlock(Mailspool,mailbox_name);
unlink(Workfile_name);
quit_session(ccb);
}
} else
quit_session(ccb);
break;
case XFER:
fprintf(fd,"%s\n",ccb->buf);
ccb->msg_len -= (long)(strlen(ccb->buf)+2); /* Add CRLF */
if (ccb->msg_len > 0)
return;
(void)usprintf(ccb->socket,ackd_cmd);
ccb->msg_num++;
ccb->state = SIZE;
break;
case EXIT:
if (fd != NULLFILE)
fclose(fd);
break;
default:
break;
}
}
void
quit_session(ccb)
struct pop_ccb *ccb;
{
(void)usprintf(ccb->socket,quit_cmd);
ccb->state = EXIT;
}